package org.springframework.ai.mcp.server.demo.tools;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.server.McpServerFeatures;
import io.modelcontextprotocol.spec.McpSchema;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 盐选故事爬取工具配置类，提供爬取不同来源盐选故事全文的功能。
 */
@Configuration
public class YanXuanStoryTools {

    private static final Logger logger = LoggerFactory.getLogger(YanXuanStoryTools.class);
    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36";
    private static final int TIMEOUT = 15000; // 15秒超时
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 盐选故事工具集合：包含所有盐选故事相关的工具。
     */
    @Bean
    public List<McpServerFeatures.SyncToolSpecification> yanXuanStoryToolList() {
        return List.of(createYanXuanStoryCrawlerTool());
    }

    /**
     * 创建盐选故事爬取工具。
     */
    private McpServerFeatures.SyncToolSpecification createYanXuanStoryCrawlerTool() {
        logger.info("创建盐选故事爬取工具");

        String schemaJson = """
        {
          "type": "object",
          "properties": {
            "url": {
              "type": "string",
              "description": "盐选故事的完整URL地址，例如 https://onehu.xyz/2024/02/07/47%E4%B8%8A%E5%B2%B8%E8%BF%99%E4%BB%B6%E5%B0%8F%E4%BA%8B 或 https://www.yanxuan.org/yanxuan/H/%E6%B5%B7%E7%9A%84%E5%91%B3%E9%81%93%E9%BE%99%E7%9F%A5%E9%81%93/%E8%BF%BD%E4%BD%A0%E6%97%B6%E9%AB%98%E5%86%B7%E4%B8%8D%E8%BF%BD%E4%BA%86%E5%A7%94%E5%B1%88%E4%BB%80%E4%B9%88/"
            }
          },
          "required": ["url"]
        }
        """;

        McpSchema.Tool tool = new McpSchema.Tool(
            "yanxuan_story_crawler",
            "爬取盐选故事全文内容，支持多个来源的盐选故事网站",
            schemaJson
        );

        return new McpServerFeatures.SyncToolSpecification(
            tool,
            (exchange, arguments) -> {
                try {
                    String url = arguments.get("url").toString();
                    if (url == null || url.trim().isEmpty()) {
                        return new McpSchema.CallToolResult("错误：必须提供有效的URL地址", true);
                    }

                    logger.info("开始爬取盐选故事，URL: {}", url);

                    // 爬取网页内容
                    Document doc = Jsoup.connect(url)
                            .userAgent(USER_AGENT)
                            .timeout(TIMEOUT)
                            .get();

                    // 解析故事内容
                    Map<String, Object> storyData = parseStoryContent(doc, url);

                    // 检查是否成功获取到内容
                    if (storyData.isEmpty() || !storyData.containsKey("content")) {
                        return new McpSchema.CallToolResult("未能获取到故事内容，可能是网站结构已改变或不支持的URL格式", true);
                    }

                    // 转换为JSON字符串
                    String resultJson = objectMapper.writeValueAsString(storyData);

                    String response = String.format("成功获取盐选故事！\n%s", resultJson);

                    return new McpSchema.CallToolResult(response, false);

                } catch (IOException e) {
                    logger.error("爬取盐选故事失败", e);
                    return new McpSchema.CallToolResult("爬取失败: " + e.getMessage(), true);
                } catch (Exception e) {
                    logger.error("处理盐选故事时发生错误", e);
                    return new McpSchema.CallToolResult("处理故事数据时发生错误: " + e.getMessage(), true);
                }
            }
        );
    }

    /**
     * 解析故事内容，根据不同的网站来源使用不同的解析策略。
     */
    private Map<String, Object> parseStoryContent(Document doc, String url) {
        Map<String, Object> storyData = new HashMap<>();
        
        try {
            // 判断来源网站并使用对应的解析策略
            if (url.contains("onehu.xyz")) {
                storyData = parseOneHuStory(doc);
            } else if (url.contains("yanxuan.org")) {
                storyData = parseYanXuanOrgStory(doc);
            } else {
                // 尝试通用解析策略
                storyData = parseGenericStory(doc);
            }
            
            // 添加来源URL
            storyData.put("sourceUrl", url);
            
        } catch (Exception e) {
            logger.error("解析故事内容时发生错误", e);
            throw new RuntimeException("解析故事内容失败: " + e.getMessage(), e);
        }
        
        return storyData;
    }
    
    /**
     * 解析onehu.xyz网站的故事内容
     */
    private Map<String, Object> parseOneHuStory(Document doc) {
        Map<String, Object> storyData = new HashMap<>();
        
        // 提取标题
        Element titleElement = doc.select("h1.entry-title").first();
        if (titleElement != null) {
            storyData.put("title", titleElement.text().trim());
        }
        
        // 提取内容 - onehu.xyz的内容通常在.entry-content或.post-content中
        Element contentElement = doc.select(".entry-content").first();
        if (contentElement == null) {
            contentElement = doc.select(".post-content").first();
        }
        if (contentElement == null) {
            contentElement = doc.select("article").first();
        }
        
        if (contentElement != null) {
            // 移除不需要的元素
            contentElement.select("script, style, .ads, .advertisement, .share-buttons, .related-posts").remove();
            
            // 提取纯文本内容
            String content = contentElement.text().trim();
            storyData.put("content", content);
        }
        
        // 提取作者信息
        Element authorElement = doc.select(".author-name, .post-author, .by-author").first();
        if (authorElement != null) {
            storyData.put("author", authorElement.text().trim());
        }
        
        return storyData;
    }
    
    /**
     * 解析yanxuan.org网站的故事内容
     */
    private Map<String, Object> parseYanXuanOrgStory(Document doc) {
        Map<String, Object> storyData = new HashMap<>();
        
        // 提取标题
        Element titleElement = doc.select("h1").first();
        if (titleElement != null) {
            storyData.put("title", titleElement.text().trim());
        }
        
        // 提取内容 - yanxuan.org的内容通常在特定结构的div中
        Element contentElement = doc.select(".content, .article-content, .post-content, .story-content").first();
        if (contentElement == null) {
            // 尝试更通用的选择器
            contentElement = doc.select("main").first();
        }
        if (contentElement == null) {
            contentElement = doc.select("article").first();
        }
        
        if (contentElement != null) {
            // 移除不需要的元素
            contentElement.select("script, style, .ads, .advertisement, .nav, .header, .footer, .sidebar").remove();
            
            // 提取纯文本内容
            String content = contentElement.text().trim();
            storyData.put("content", content);
        }
        
        // 提取作者信息
        Element authorElement = doc.select(".author, .byline, .writer").first();
        if (authorElement != null) {
            storyData.put("author", authorElement.text().trim());
        }
        
        return storyData;
    }
    
    /**
     * 通用故事内容解析策略，用于未知来源的网站
     */
    private Map<String, Object> parseGenericStory(Document doc) {
        Map<String, Object> storyData = new HashMap<>();
        
        // 尝试提取标题
        Element titleElement = doc.select("h1, .title, .post-title, .entry-title").first();
        if (titleElement != null) {
            storyData.put("title", titleElement.text().trim());
        }
        
        // 尝试提取主要内容
        Element contentElement = doc.select("main, article, .content, .post-content, .entry-content, .story-content").first();
        
        if (contentElement != null) {
            // 移除不需要的元素
            contentElement.select("script, style, nav, header, footer, .ads, .advertisement, .sidebar, .comments").remove();
            
            // 提取纯文本内容
            String content = contentElement.text().trim();
            storyData.put("content", content);
        }
        
        // 尝试提取作者信息
        Element authorElement = doc.select(".author, .byline, .writer, .post-author").first();
        if (authorElement != null) {
            storyData.put("author", authorElement.text().trim());
        }
        
        return storyData;
    }
}